package com.kamistoat.netty.netty.http;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;

import java.net.URI;
import java.nio.charset.StandardCharsets;

/**
 * Netty-Http服务端handler
 * SimpleChannelInboundHandler 就是原来的 ChannelInboundHandlerAdapter 的一个子类，继承时需要指定该Handler处理哪种数据。
 * 该子类只有一个方法待实现，相比于其父类来说更简单一些。
 * HttpObject表示客户端和服务器端相互通信的数据被封装成 HttpObject
 */
public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    /**
     * SimpleChannelInboundHandler 唯一的方法，直接完成read+write
     * @param channelHandlerContext 上下文
     * @param httpObject 在继承类时就要指定该类将处理哪种数据。这里会自动填上
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject httpObject) throws Exception {
        // 判断 HttpObject是不是HttpRequest请求
        // 因为Pipeline中有很多handler，Channel会在handler中顺序传递，所以真的进来的时候谁也不知道到底啥啥数据，因此需要做一下类型过滤
        if(httpObject instanceof HttpRequest){
            System.out.println("Client地址: " + channelHandlerContext.channel().remoteAddress());

            HttpRequest httpRequest = (HttpRequest) httpObject;
            // 获取uri
            URI uri = new URI(httpRequest.uri());
            if("/favicon.ico".equals(uri.getPath())){
                System.out.println("请求静态资源，不做响应");
                return;
            }

            ByteBuf content = Unpooled.copiedBuffer("hello, i'm Server", StandardCharsets.UTF_8);
            // 构造一个HttpResponse并设置协议版本号，并设置返回码为200，content将作为响应数据
            // 该类同样是Netty提供的库类
            DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            // 设置响应header
            // 1. 直接以文本格式返回响应数据
            httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            // 2. 定义响应数据的长度
            httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
            // 将构建好的HttpResponse进行返回
            channelHandlerContext.writeAndFlush(httpResponse);
        }
    }
}
